{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3D Alexandria Database\n",
    "\n",
    "\n",
    "![alexandria_3d](images/alexandria_3d_database.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install parquetdb\n",
    "!pip install pymatgen"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import json\n",
    "import os\n",
    "import logging\n",
    "from glob import glob\n",
    "import shutil\n",
    "import time\n",
    "\n",
    "import numpy as np\n",
    "from pyarrow import compute as pc\n",
    "\n",
    "from parquetdb.core.parquetdb import LoadConfig, NormalizeConfig\n",
    "from parquetdb.utils.general_utils import timeit\n",
    "from parquetdb import ParquetDB, config\n",
    "from parquetdb.utils.external_utils import download_alexandria_3d_database\n",
    "\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Setup data directories"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "base_dir = os.path.join(config.data_dir, \"external\", \"alexandria\", \"AlexandriaDB\")\n",
    "benchmark_dir = os.path.join(config.data_dir, \"benchmarks\", \"alexandria\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Download the database\n",
    "\n",
    "Lets download the database"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting task: download_alexandria_database\n",
      "Database downloaded already. Skipping download.\n",
      "Done with task: download_alexandria_database\n",
      "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n",
      "Z:\\data\\parquetdb\\data\\external\\alexandria\\uncompressed\n"
     ]
    }
   ],
   "source": [
    "def download_alexandria_database(base_dir, from_scratch=False):\n",
    "    print(\"Starting task: download_alexandria_database\")\n",
    "    if from_scratch and os.path.exists(base_dir):\n",
    "        print(f\"Removing existing directory: {base_dir}\")\n",
    "        shutil.rmtree(base_dir, ignore_errors=True)\n",
    "\n",
    "    # Here we download the database and save it to the data directory\n",
    "    output_dir = os.path.join(config.data_dir, \"external\", \"alexandria\")\n",
    "    alexandria_dir = download_alexandria_3d_database(output_dir, n_cores=8)\n",
    "    print(\"Done with task: download_alexandria_database\")\n",
    "    print(\"-\" * 200)\n",
    "    return alexandria_dir\n",
    "\n",
    "\n",
    "alexandria_dir = download_alexandria_database(base_dir, from_scratch=False)\n",
    "print(alexandria_dir)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Creating the database\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[INFO] 2025-04-22 09:14:49 - parquetdb.core.parquetdb[205][__init__] - Initializing ParquetDB with db_path: Z:\\data\\parquetdb\\data\\external\\alexandria\\AlexandriaDB\\alexandria_3D\n",
      "[INFO] 2025-04-22 09:14:49 - parquetdb.core.parquetdb[207][__init__] - verbose: 1\n",
      "============================================================\n",
      "PARQUETDB SUMMARY\n",
      "============================================================\n",
      "Database path: Z:\\data\\parquetdb\\data\\external\\alexandria\\AlexandriaDB\\alexandria_3D\n",
      "\n",
      "• Number of columns: 128\n",
      "• Number of rows: 4389295\n",
      "• Number of files: 1\n",
      "• Number of rows per file: [4389295]\n",
      "• Number of row groups per file: [22]\n",
      "• Serialized metadata size per file: [377883] Bytes\n",
      "\n",
      "############################################################\n",
      "METADATA\n",
      "############################################################\n",
      "\n",
      "############################################################\n",
      "COLUMN DETAILS\n",
      "############################################################\n",
      "\n"
     ]
    }
   ],
   "source": [
    "db = ParquetDB(db_path=os.path.join(base_dir, \"alexandria_3D\"))\n",
    "print(db)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Lets Define some dictionaries to store some benchmark results\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "benchmark_dict = {\n",
    "    \"create_times\": [],\n",
    "    \"json_load_times\": [],\n",
    "    \"n_rows_per_file\": [],\n",
    "}\n",
    "\n",
    "task_benchmark_dict = {\"task_names\": [], \"task_times\": []}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Inputing the data\n",
    "\n",
    "Here I am just iterating over the json files and creating the database. I am also storing how long it takes to load each json file, how many materials, and how long it takes to input the data into the database.\n",
    "\n",
    "This dataset is rather large, so you may have to choose the normalization parameters depending on how much RAM you have. If you do not have enough tweak the `batch_size`, `batch_readahead`, `fragment_readahead` parameters.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting task: create_database_if_empty\n",
      "Done with task: create_database_if_empty\n",
      "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "def create_database_if_empty(db, alexandria_dir, normalize_config=NormalizeConfig()):\n",
    "    \"\"\"_summary_\n",
    "\n",
    "    Parameters\n",
    "    ----------\n",
    "    db : ParquetDB Instance\n",
    "        The database instance to create the dataset on.\n",
    "    alexandria_dir : str\n",
    "        The directory containing the json files to input into the database.\n",
    "\n",
    "    Returns\n",
    "    -------\n",
    "    _type_\n",
    "        _description_\n",
    "    \"\"\"\n",
    "    print(\"Starting task: create_database_if_empty\")\n",
    "\n",
    "    start_time = time.time()\n",
    "\n",
    "    json_load_times = []\n",
    "    create_times = []\n",
    "    n_materials_per_file = []\n",
    "    if db.is_empty():\n",
    "        print(\"The dataset does not exist. Creating it.\")\n",
    "        json_files = glob(os.path.join(alexandria_dir, \"*.json\"))\n",
    "        for json_file in json_files[:]:\n",
    "\n",
    "            start_time = time.time()\n",
    "            with open(json_file, \"r\") as f:\n",
    "                data = json.load(f)\n",
    "            json_load_time = time.time() - start_time\n",
    "\n",
    "            base_name = os.path.basename(json_file)\n",
    "            n_materials = len(data[\"entries\"])\n",
    "            print(f\"Processing file: {base_name}\")\n",
    "            print(f\"Number of materials: {n_materials}\")\n",
    "            try:\n",
    "                # Since we are importing alot of data it is best\n",
    "                # to normalize the database afterwards\n",
    "                start_time = time.time()\n",
    "                db.create(\n",
    "                    data[\"entries\"],\n",
    "                    normalize_dataset=False,\n",
    "                    normalize_config=normalize_config,\n",
    "                )\n",
    "                create_time = time.time() - start_time\n",
    "\n",
    "                create_times.append(create_time)\n",
    "                n_materials_per_file.append(n_materials)\n",
    "                json_load_times.append(json_load_time)\n",
    "\n",
    "            except Exception as e:\n",
    "                print(e)\n",
    "\n",
    "            data = None\n",
    "\n",
    "            print(f\"Time taken to create dataset: {time.time() - start_time}\")\n",
    "            print(\"-\" * 100)\n",
    "\n",
    "    print(\"Done with task: create_database_if_empty\")\n",
    "    print(\"-\" * 200)\n",
    "    return json_load_times, create_times, n_materials_per_file\n",
    "\n",
    "\n",
    "normalize_config = NormalizeConfig(\n",
    "    load_format=\"batches\",  # Uses the batch generator to normalize\n",
    "    batch_readahead=4,  # Controls the number of batches to load in memory a head of time. This will have impacts on amount of RAM consumed\n",
    "    fragment_readahead=2,  # Controls the number of files to load in memory ahead of time. This will have impacts on amount of RAM consumed\n",
    "    batch_size=100000,  # Controls the batchsize when to use when normalizing. This will have impacts on amount of RAM consumed\n",
    "    max_rows_per_file=100000,  # Controls the max number of rows per parquet file\n",
    "    max_rows_per_group=100000,\n",
    ")  # Controls the max number of rows per group parquet\n",
    "\n",
    "\n",
    "json_load_times, create_times, n_materials_per_file = create_database_if_empty(\n",
    "    db, alexandria_dir, normalize_config=normalize_config\n",
    ")\n",
    "\n",
    "benchmark_dict[\"create_times\"] = create_times\n",
    "benchmark_dict[\"json_load_times\"] = json_load_times\n",
    "benchmark_dict[\"n_rows_per_file\"] = n_materials_per_file"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Normalizing the dataset\n",
    "\n",
    "It is best practive to normalize the dataset after all the data has been inputed. This will optimize the performance of the database.\n",
    "\n",
    "First let's see how the data is distributed in the row groups.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "============================================================\n",
      "PARQUETDB SUMMARY\n",
      "============================================================\n",
      "Database path: Z:\\data\\parquetdb\\data\\external\\alexandria\\AlexandriaDB\\alexandria_3D\n",
      "\n",
      "• Number of columns: 128\n",
      "• Number of rows: 4389295\n",
      "• Number of files: 1\n",
      "• Number of rows per file: [4389295]\n",
      "• Number of row groups per file: [22]\n",
      "• Number of rows per row group per file: \n",
      "    - alexandria_3D_0.parquet:\n",
      "        - Row group 0: 200000 rows\n",
      "        - Row group 1: 200000 rows\n",
      "        - Row group 2: 200000 rows\n",
      "        - Row group 3: 200000 rows\n",
      "        - Row group 4: 200000 rows\n",
      "        - Row group 5: 200000 rows\n",
      "        - Row group 6: 200000 rows\n",
      "        - Row group 7: 200000 rows\n",
      "        - Row group 8: 200000 rows\n",
      "        - Row group 9: 200000 rows\n",
      "        - Row group 10: 200000 rows\n",
      "        - Row group 11: 200000 rows\n",
      "        - Row group 12: 200000 rows\n",
      "        - Row group 13: 200000 rows\n",
      "        - Row group 14: 200000 rows\n",
      "        - Row group 15: 200000 rows\n",
      "        - Row group 16: 200000 rows\n",
      "        - Row group 17: 200000 rows\n",
      "        - Row group 18: 200000 rows\n",
      "        - Row group 19: 200000 rows\n",
      "        - Row group 20: 200000 rows\n",
      "        - Row group 21: 189295 rows\n",
      "• Serialized metadata size per file: [377883] Bytes\n",
      "\n",
      "############################################################\n",
      "METADATA\n",
      "############################################################\n",
      "\n",
      "############################################################\n",
      "COLUMN DETAILS\n",
      "############################################################\n",
      "\n"
     ]
    }
   ],
   "source": [
    "summary = db.summary(show_row_group_metadata=True)\n",
    "print(summary)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's check the file size of the parquet files."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "alexandria_3D_0.parquet: 2767.1490955352783 MB\n"
     ]
    }
   ],
   "source": [
    "def list_file_sizes(directory, in_MB=True):\n",
    "    \"\"\"Lists the size of files in a directory.\n",
    "\n",
    "    Args:\n",
    "      directory: The path to the directory.\n",
    "    \"\"\"\n",
    "    file_sizes = {}\n",
    "    for filename in os.listdir(directory):\n",
    "        file_path = os.path.join(directory, filename)\n",
    "        if os.path.isfile(file_path):\n",
    "            file_size = os.path.getsize(file_path)\n",
    "            if in_MB:\n",
    "                file_size = file_size / (1024 * 1024)\n",
    "            file_sizes[filename] = file_size\n",
    "    return file_sizes\n",
    "\n",
    "\n",
    "file_sizes = list_file_sizes(db.db_path)\n",
    "\n",
    "for file, size in file_sizes.items():\n",
    "    print(f\"{file}: {size} MB\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's also check the size of the row groups.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "alexandria_3D_0.parquet\n",
      "     0: 201.08054542541504 MB\n",
      "     1: 220.59319686889648 MB\n",
      "     2: 197.38053512573242 MB\n",
      "     3: 187.26845264434814 MB\n",
      "     4: 227.97186374664307 MB\n",
      "     5: 192.6089096069336 MB\n",
      "     6: 216.52346420288086 MB\n",
      "     7: 198.00727558135986 MB\n",
      "     8: 227.92319583892822 MB\n",
      "     9: 226.87678337097168 MB\n",
      "     10: 244.66320514678955 MB\n",
      "     11: 215.52607440948486 MB\n",
      "     12: 198.7313060760498 MB\n",
      "     13: 204.19597339630127 MB\n",
      "     14: 192.36825561523438 MB\n",
      "     15: 217.40732860565186 MB\n",
      "     16: 215.3526430130005 MB\n",
      "     17: 201.5632438659668 MB\n",
      "     18: 189.40394115447998 MB\n",
      "     19: 200.09145641326904 MB\n",
      "     20: 208.74722480773926 MB\n",
      "     21: 206.02736282348633 MB\n",
      "Average row group size: 208.65055626088923 MB\n"
     ]
    }
   ],
   "source": [
    "row_group_metadata_per_file = db.get_parquet_file_row_group_metadata_per_file(\n",
    "    as_dict=True\n",
    ")\n",
    "row_group_size_per_file = {}\n",
    "sum_row_group_size = 0\n",
    "num_row_groups = 0\n",
    "for file, row_group_metadata in row_group_metadata_per_file.items():\n",
    "    print(f\"{file}\")\n",
    "    row_group_size_per_file[file] = {}\n",
    "    for row_group, metadata in row_group_metadata.items():\n",
    "        row_group_size_per_file[file][row_group] = metadata[\"total_byte_size\"] / (\n",
    "            1024 * 1024\n",
    "        )\n",
    "        sum_row_group_size += row_group_size_per_file[file][row_group]\n",
    "        num_row_groups += 1\n",
    "        print(f\"     {row_group}: {row_group_size_per_file[file][row_group]} MB\")\n",
    "\n",
    "print(f\"Average row group size: {sum_row_group_size/num_row_groups} MB\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For the most optimal performance we should aim for 2GB per file and about 200-500MB per row group.\n",
    "\n",
    "Currently for a row group with 32,768 rows the size of the row group is ~30MB. To get to 200MB we should put 200MB/30MB more rows in the row group or ~200,000 rows.\n",
    "\n",
    "If each rowgroup is about 200MB at 200,000 rows then we should have 2GB/200MB = 10 row groups per file. or 2,000,000 rows per file. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting task: normalize_dataset\n",
      "Done with task: normalize_dataset\n",
      "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n",
      "============================================================\n",
      "PARQUETDB SUMMARY\n",
      "============================================================\n",
      "Database path: Z:\\data\\parquetdb\\data\\external\\alexandria\\AlexandriaDB\\alexandria_3D\n",
      "\n",
      "• Number of columns: 128\n",
      "• Number of rows: 4389295\n",
      "• Number of files: 3\n",
      "• Number of rows per file: [2000000, 2000000, 389295]\n",
      "• Number of row groups per file: [10, 10, 2]\n",
      "• Number of rows per row group per file: \n",
      "    - alexandria_3D_0.parquet:\n",
      "        - Row group 0: 200000 rows\n",
      "        - Row group 1: 200000 rows\n",
      "        - Row group 2: 200000 rows\n",
      "        - Row group 3: 200000 rows\n",
      "        - Row group 4: 200000 rows\n",
      "        - Row group 5: 200000 rows\n",
      "        - Row group 6: 200000 rows\n",
      "        - Row group 7: 200000 rows\n",
      "        - Row group 8: 200000 rows\n",
      "        - Row group 9: 200000 rows\n",
      "    - alexandria_3D_1.parquet:\n",
      "        - Row group 0: 200000 rows\n",
      "        - Row group 1: 200000 rows\n",
      "        - Row group 2: 200000 rows\n",
      "        - Row group 3: 200000 rows\n",
      "        - Row group 4: 200000 rows\n",
      "        - Row group 5: 200000 rows\n",
      "        - Row group 6: 200000 rows\n",
      "        - Row group 7: 200000 rows\n",
      "        - Row group 8: 200000 rows\n",
      "        - Row group 9: 200000 rows\n",
      "    - alexandria_3D_2.parquet:\n",
      "        - Row group 0: 200000 rows\n",
      "        - Row group 1: 189295 rows\n",
      "• Serialized metadata size per file: [180572, 178843, 48142] Bytes\n",
      "\n",
      "############################################################\n",
      "METADATA\n",
      "############################################################\n",
      "\n",
      "############################################################\n",
      "COLUMN DETAILS\n",
      "############################################################\n",
      "\n"
     ]
    }
   ],
   "source": [
    "def normalize_dataset(db, normalize_config=NormalizeConfig()):\n",
    "    task_name = \"normalize_dataset\"\n",
    "    print(\"Starting task: normalize_dataset\")\n",
    "\n",
    "    db.normalize(normalize_config=normalize_config)\n",
    "    print(\"Done with task: normalize_dataset\")\n",
    "    print(\"-\" * 200)\n",
    "    return task_name\n",
    "\n",
    "\n",
    "normalize_config = NormalizeConfig(\n",
    "    load_format=\"batches\",  # Uses the batch generator to normalize\n",
    "    batch_readahead=4,  # Controls the number of batches to load in memory a head of time. This will have impacts on amount of RAM consumed\n",
    "    fragment_readahead=1,  # Controls the number of files to load in memory ahead of time. This will have impacts on amount of RAM consumed\n",
    "    batch_size=10000,  # Controls the batchsize when to use when normalizing. This will have impacts on amount of RAM consumed\n",
    "    max_rows_per_file=2000000,  # Controls the max number of rows per parquet file\n",
    "    max_rows_per_group=200000,\n",
    "    min_rows_per_group=200000,\n",
    ")  # Controls the max number of rows per group parquet file\n",
    "normalize_dataset(db, normalize_config=normalize_config)\n",
    "print(db.summary(show_row_group_metadata=True))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's check the file sizes and row group sizes again."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "alexandria_3D_0.parquet: 1261.4758415222168 MB\n",
      "alexandria_3D_1.parquet: 1251.6552095413208 MB\n",
      "alexandria_3D_2.parquet: 254.18556213378906 MB\n",
      "alexandria_3D_0.parquet\n",
      "     0: 201.72274780273438 MB\n",
      "     1: 219.45661544799805 MB\n",
      "     2: 197.442889213562 MB\n",
      "     3: 187.3084535598755 MB\n",
      "     4: 227.44355964660645 MB\n",
      "     5: 192.6088399887085 MB\n",
      "     6: 216.52346420288086 MB\n",
      "     7: 198.00727558135986 MB\n",
      "     8: 227.92319583892822 MB\n",
      "     9: 226.87678337097168 MB\n",
      "alexandria_3D_1.parquet\n",
      "     0: 244.66320514678955 MB\n",
      "     1: 215.52607440948486 MB\n",
      "     2: 198.7313995361328 MB\n",
      "     3: 203.92721366882324 MB\n",
      "     4: 191.9358901977539 MB\n",
      "     5: 218.27143096923828 MB\n",
      "     6: 215.63258838653564 MB\n",
      "     7: 201.5486354827881 MB\n",
      "     8: 191.0305995941162 MB\n",
      "     9: 199.67366981506348 MB\n",
      "alexandria_3D_2.parquet\n",
      "     0: 208.74722480773926 MB\n",
      "     1: 206.0274362564087 MB\n",
      "Average row group size: 208.6831451329318 MB\n"
     ]
    }
   ],
   "source": [
    "file_sizes = list_file_sizes(db.db_path)\n",
    "\n",
    "for file, size in file_sizes.items():\n",
    "    print(f\"{file}: {size} MB\")\n",
    "\n",
    "\n",
    "row_group_metadata_per_file = db.get_parquet_file_row_group_metadata_per_file(\n",
    "    as_dict=True\n",
    ")\n",
    "row_group_size_per_file = {}\n",
    "sum_row_group_size = 0\n",
    "num_row_groups = 0\n",
    "for file, row_group_metadata in row_group_metadata_per_file.items():\n",
    "    print(f\"{file}\")\n",
    "    row_group_size_per_file[file] = {}\n",
    "    for row_group, metadata in row_group_metadata.items():\n",
    "        row_group_size_per_file[file][row_group] = metadata[\"total_byte_size\"] / (\n",
    "            1024 * 1024\n",
    "        )\n",
    "        sum_row_group_size += row_group_size_per_file[file][row_group]\n",
    "        num_row_groups += 1\n",
    "        print(f\"     {row_group}: {row_group_size_per_file[file][row_group]} MB\")\n",
    "\n",
    "print(f\"Average row group size: {sum_row_group_size/num_row_groups} MB\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here we see that the row groups are about 200MB and the file sizes are a 1GB. This is a little smaller because the less files the more common metadata is stored together. I would try to store all the data in the same file in this case"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting task: normalize_dataset\n",
      "Done with task: normalize_dataset\n",
      "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n",
      "============================================================\n",
      "PARQUETDB SUMMARY\n",
      "============================================================\n",
      "Database path: Z:\\data\\parquetdb\\data\\external\\alexandria\\AlexandriaDB\\alexandria_3D\n",
      "\n",
      "• Number of columns: 128\n",
      "• Number of rows: 4389295\n",
      "• Number of files: 1\n",
      "• Number of rows per file: [4389295]\n",
      "• Number of row groups per file: [22]\n",
      "• Number of rows per row group per file: \n",
      "    - alexandria_3D_0.parquet:\n",
      "        - Row group 0: 200000 rows\n",
      "        - Row group 1: 200000 rows\n",
      "        - Row group 2: 200000 rows\n",
      "        - Row group 3: 200000 rows\n",
      "        - Row group 4: 200000 rows\n",
      "        - Row group 5: 200000 rows\n",
      "        - Row group 6: 200000 rows\n",
      "        - Row group 7: 200000 rows\n",
      "        - Row group 8: 200000 rows\n",
      "        - Row group 9: 200000 rows\n",
      "        - Row group 10: 200000 rows\n",
      "        - Row group 11: 200000 rows\n",
      "        - Row group 12: 200000 rows\n",
      "        - Row group 13: 200000 rows\n",
      "        - Row group 14: 200000 rows\n",
      "        - Row group 15: 200000 rows\n",
      "        - Row group 16: 200000 rows\n",
      "        - Row group 17: 200000 rows\n",
      "        - Row group 18: 200000 rows\n",
      "        - Row group 19: 200000 rows\n",
      "        - Row group 20: 200000 rows\n",
      "        - Row group 21: 189295 rows\n",
      "• Serialized metadata size per file: [377929] Bytes\n",
      "\n",
      "############################################################\n",
      "METADATA\n",
      "############################################################\n",
      "\n",
      "############################################################\n",
      "COLUMN DETAILS\n",
      "############################################################\n",
      "\n",
      "alexandria_3D_0.parquet: 2767.2842226028442 MB\n"
     ]
    }
   ],
   "source": [
    "normalize_config = NormalizeConfig(\n",
    "    load_format=\"batches\",  # Uses the batch generator to normalize\n",
    "    batch_readahead=4,  # Controls the number of batches to load in memory a head of time. This will have impacts on amount of RAM consumed\n",
    "    fragment_readahead=1,  # Controls the number of files to load in memory ahead of time. This will have impacts on amount of RAM consumed\n",
    "    batch_size=10000,  # Controls the batchsize when to use when normalizing. This will have impacts on amount of RAM consumed\n",
    "    max_rows_per_file=5000000,  # Controls the max number of rows per parquet file\n",
    "    max_rows_per_group=200000,\n",
    "    min_rows_per_group=200000,\n",
    ")  # Controls the max number of rows per group parquet file\n",
    "normalize_dataset(db, normalize_config=normalize_config)\n",
    "print(db.summary(show_row_group_metadata=True))\n",
    "\n",
    "file_sizes = list_file_sizes(db.db_path)\n",
    "for file, size in file_sizes.items():\n",
    "    print(f\"{file}: {size} MB\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Basic Operations\n",
    "\n",
    "In this section we are going to test the performance of ParquetDB for basic operations.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Reading a single column\n",
    "\n",
    "\n",
    "If one were to want a single property for all materials in alexandria, if it were in json format, we would have to iterate  over and read all the json files to collect the property. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting task: read_single_column\n",
      "(4389295, 1)\n",
      "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n",
      "Time to read from parquetdb: 0.04 seconds\n",
      "Time to read from json: 0.00 seconds\n"
     ]
    }
   ],
   "source": [
    "total_time_to_read_from_json = sum(benchmark_dict[\"json_load_times\"])\n",
    "\n",
    "\n",
    "def read_single_column(db):\n",
    "    task_name = \"read_single_column\"\n",
    "    print(\"Starting task: read_single_column\")\n",
    "    table = db.read(columns=[\"id\"], load_format=\"table\")\n",
    "    print(table.shape)\n",
    "    print(\"-\" * 200)\n",
    "    return task_name\n",
    "\n",
    "\n",
    "start_time = time.time()\n",
    "task_name = read_single_column(db)\n",
    "read_single_column_time = time.time() - start_time\n",
    "\n",
    "task_benchmark_dict[\"task_names\"].append(task_name)\n",
    "task_benchmark_dict[\"task_times\"].append(read_single_column_time)\n",
    "\n",
    "print(f\"Time to read from parquetdb: {read_single_column_time:.2f} seconds\")\n",
    "print(f\"Time to read from json: {total_time_to_read_from_json:.2f} seconds\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Reading specific ids\n",
    "\n",
    "Now, if we were to want speific columns, at minimum time to do this in json format would be the same time as iterating over the json files.\n",
    "\n",
    "In ParquetDB, it is much simpler and less memory intensive to read specific ids.\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting task: read_specific_ids\n",
      "0      10000\n",
      "1          0\n",
      "2         10\n",
      "3        100\n",
      "4       1000\n",
      "5     100000\n",
      "6    1000000\n",
      "Name: id, dtype: int64\n",
      "                   @class                            @module  composition.Ac  \\\n",
      "0  ComputedStructureEntry  pymatgen.entries.computed_entries             2.0   \n",
      "1  ComputedStructureEntry  pymatgen.entries.computed_entries             1.0   \n",
      "2  ComputedStructureEntry  pymatgen.entries.computed_entries             1.0   \n",
      "3  ComputedStructureEntry  pymatgen.entries.computed_entries             1.0   \n",
      "4  ComputedStructureEntry  pymatgen.entries.computed_entries             2.0   \n",
      "\n",
      "   composition.Ag  composition.Al  composition.Ar  composition.As  \\\n",
      "0             NaN             NaN             NaN             NaN   \n",
      "1             NaN             NaN             NaN             NaN   \n",
      "2             NaN             NaN             NaN             NaN   \n",
      "3             NaN             NaN             NaN             NaN   \n",
      "4             NaN             NaN             NaN             NaN   \n",
      "\n",
      "   composition.Au  composition.B  composition.Ba  ...  structure.lattice.a  \\\n",
      "0             NaN            NaN             NaN  ...             4.829086   \n",
      "1             NaN            NaN             NaN  ...            10.091510   \n",
      "2             NaN            NaN             NaN  ...            15.519920   \n",
      "3             NaN            NaN             NaN  ...             5.789011   \n",
      "4             NaN            NaN             NaN  ...             8.695520   \n",
      "\n",
      "   structure.lattice.alpha  structure.lattice.b  structure.lattice.beta  \\\n",
      "0                90.000000             4.829086               90.000000   \n",
      "1               109.471217            10.091510              109.471222   \n",
      "2                89.997963            11.000739               89.996986   \n",
      "3               111.411199             8.109282               99.469696   \n",
      "4                69.601810             7.709933               55.506047   \n",
      "\n",
      "   structure.lattice.c  structure.lattice.gamma  \\\n",
      "0             9.745281                90.000000   \n",
      "1            10.091511               109.471219   \n",
      "2             5.192681                45.191179   \n",
      "3             8.109282                99.469696   \n",
      "4             7.709933                55.506037   \n",
      "\n",
      "                            structure.lattice.matrix  structure.lattice.pbc  \\\n",
      "0  [4.82908586, 0.0, 0.0, 0.0, 4.82908586, 0.0, 0...     [True, True, True]   \n",
      "1  [9.51436671, 2e-08, -3.36383678, -4.75718337, ...     [True, True, True]   \n",
      "2  [15.51989271, -0.00721914, 0.02799947, 7.75631...     [True, True, True]   \n",
      "3  [5.78373142, -0.13705652, -0.20571227, -1.1463...     [True, True, True]   \n",
      "4  [7.92465233, 0.98010515, 3.44257929, 3.2101699...     [True, True, True]   \n",
      "\n",
      "   structure.lattice.volume                                    structure.sites  \n",
      "0                227.260645  [{'abc': [0.0, 0.5, 0.2399718], 'label': 'Ac',...  \n",
      "1                791.127799  [{'abc': [0.0, 0.0, 0.0], 'label': 'Ac', 'prop...  \n",
      "2                628.973408  [{'abc': [3e-06, 3e-06, 0.0], 'label': 'Ac', '...  \n",
      "3                338.968680  [{'abc': [0.5, 0.0, 0.0], 'label': 'Ac', 'prop...  \n",
      "4                350.818535  [{'abc': [0.83221258, 0.94982224, 0.94982224],...  \n",
      "\n",
      "[5 rows x 128 columns]\n",
      "(7, 128)\n",
      "[dtype('O'), dtype('int64'), dtype('float64')]\n",
      "Data : 129\n",
      "['@class', '@module', 'composition.Ac', 'composition.Ag', 'composition.Al', 'composition.Ar', 'composition.As', 'composition.Au', 'composition.B', 'composition.Ba', 'composition.Be', 'composition.Bi', 'composition.Br', 'composition.C', 'composition.Ca', 'composition.Cd', 'composition.Ce', 'composition.Cl', 'composition.Co', 'composition.Cr', 'composition.Cs', 'composition.Cu', 'composition.Dy', 'composition.Er', 'composition.Eu', 'composition.F', 'composition.Fe', 'composition.Ga', 'composition.Gd', 'composition.Ge', 'composition.H', 'composition.He', 'composition.Hf', 'composition.Hg', 'composition.Ho', 'composition.I', 'composition.In', 'composition.Ir', 'composition.K', 'composition.Kr', 'composition.La', 'composition.Li', 'composition.Lu', 'composition.Mg', 'composition.Mn', 'composition.Mo', 'composition.N', 'composition.Na', 'composition.Nb', 'composition.Nd', 'composition.Ne', 'composition.Ni', 'composition.Np', 'composition.O', 'composition.Os', 'composition.P', 'composition.Pa', 'composition.Pb', 'composition.Pd', 'composition.Pm', 'composition.Pr', 'composition.Pt', 'composition.Pu', 'composition.Rb', 'composition.Re', 'composition.Rh', 'composition.Ru', 'composition.S', 'composition.Sb', 'composition.Sc', 'composition.Se', 'composition.Si', 'composition.Sm', 'composition.Sn', 'composition.Sr', 'composition.Ta', 'composition.Tb', 'composition.Tc', 'composition.Te', 'composition.Th', 'composition.Ti', 'composition.Tl', 'composition.Tm', 'composition.U', 'composition.V', 'composition.W', 'composition.Xe', 'composition.Y', 'composition.Yb', 'composition.Zn', 'composition.Zr', 'correction', 'data.band_gap_dir', 'data.band_gap_ind', 'data.decomposition', 'data.dos_ef', 'data.e_above_hull', 'data.e_form', 'data.e_phase_separation', 'data.elements', 'data.energy_corrected', 'data.energy_total', 'data.formula', 'data.location', 'data.mat_id', 'data.nsites', 'data.prototype_id', 'data.spg', 'data.stress', 'data.total_mag', 'energy', 'energy_adjustments', 'entry_id', 'id', 'parameters.dummy_field', 'structure.@class', 'structure.@module', 'structure.charge', 'structure.lattice.a', 'structure.lattice.alpha', 'structure.lattice.b', 'structure.lattice.beta', 'structure.lattice.c', 'structure.lattice.gamma', 'structure.lattice.matrix', 'structure.lattice.pbc', 'structure.lattice.volume', 'structure.sites']\n",
      "Done with task: read_specific_ids\n",
      "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n",
      "Time to read from parquetdb: 4.16 seconds\n",
      "Time to read from json: 0.00 seconds\n"
     ]
    }
   ],
   "source": [
    "def read_specific_ids(db):\n",
    "    task_name = \"read_specific_ids\"\n",
    "    print(\"Starting task: read_specific_ids\")\n",
    "    table = db.read(\n",
    "        ids=[\n",
    "            0,\n",
    "            10,\n",
    "            100,\n",
    "            1000,\n",
    "            10000,\n",
    "            100000,\n",
    "            1000000,\n",
    "        ],  # Controls which rows we want to read\n",
    "        load_format=\"table\",  # Controls the output format. The options are 'table', 'batches', `dataset`.\n",
    "    )\n",
    "\n",
    "    df = table.to_pandas()  # Converts the table to a pandas dataframe\n",
    "    print(df[\"id\"])\n",
    "    print(df.head())\n",
    "    print(df.shape)\n",
    "\n",
    "    print(f\"Data : {df.iloc[0]['data.spg']}\")\n",
    "    print(list(df.columns))\n",
    "    print(\"Done with task: read_specific_ids\")\n",
    "    print(\"-\" * 200)\n",
    "    return task_name\n",
    "\n",
    "\n",
    "start_time = time.time()\n",
    "task_name = read_specific_ids(db)\n",
    "read_specific_ids_time = time.time() - start_time\n",
    "\n",
    "task_benchmark_dict[\"task_names\"].append(task_name)\n",
    "task_benchmark_dict[\"task_times\"].append(read_specific_ids_time)\n",
    "\n",
    "print(f\"Time to read from parquetdb: {read_specific_ids_time:.2f} seconds\")\n",
    "print(f\"Time to read from json: {total_time_to_read_from_json:.2f} seconds\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Finding the minimum and maximum of a energy\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting task: read_energy_min_max\n",
      "(4389295, 1)\n",
      "Min: -1496.5922219, Max: -0.003981\n",
      "Done with task: read_energy_min_max\n",
      "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n",
      "Time to read from parquetdb: 0.35 seconds\n",
      "Time to read from json: 0.00 seconds\n"
     ]
    }
   ],
   "source": [
    "def read_energy_min_max(db):\n",
    "    task_name = \"read_energy_min_max\"\n",
    "    print(\"Starting task: read_energy_min_max\")\n",
    "    table = db.read(columns=[\"energy\"], load_format=\"table\")\n",
    "    print(table.shape)\n",
    "\n",
    "    result = pc.min_max(table[\"energy\"])\n",
    "    # The result will be a struct with 'min' and 'max' fields\n",
    "    min_value = result[\"min\"].as_py()\n",
    "    max_value = result[\"max\"].as_py()\n",
    "\n",
    "    print(f\"Min: {min_value}, Max: {max_value}\")\n",
    "    print(\"Done with task: read_energy_min_max\")\n",
    "    print(\"-\" * 200)\n",
    "    return task_name\n",
    "\n",
    "\n",
    "start_time = time.time()\n",
    "task_name = read_energy_min_max(db)\n",
    "read_energy_min_max_time = time.time() - start_time\n",
    "\n",
    "task_benchmark_dict[\"task_names\"].append(task_name)\n",
    "task_benchmark_dict[\"task_times\"].append(read_energy_min_max_time)\n",
    "\n",
    "print(f\"Time to read from parquetdb: {read_energy_min_max_time:.2f} seconds\")\n",
    "print(f\"Time to read from json: {total_time_to_read_from_json:.2f} seconds\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Reading records filtered by energy above -1.0\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting task: read_filtered_energy_above_minus_one\n",
      "       id    energy\n",
      "0  123136 -0.063105\n",
      "1  123137 -0.125970\n",
      "2  403318 -0.972671\n",
      "3  570682 -0.907343\n",
      "4  570683 -0.901483\n",
      "(46, 2)\n",
      "Done with task: read_filtered_energy_above_minus_one\n",
      "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n",
      "Time to read from parquetdb: 0.04 seconds\n",
      "Time to read from json: 0.00 seconds\n"
     ]
    }
   ],
   "source": [
    "def read_filtered_energy_above_minus_one(db):\n",
    "    task_name = \"read_filtered_energy_above_-1\"\n",
    "\n",
    "    \"\"\"Read records filtered by energy above -1.0 and track timing.\"\"\"\n",
    "    print(\"Starting task: read_filtered_energy_above_minus_one\")\n",
    "\n",
    "    table = db.read(\n",
    "        columns=[\"id\", \"energy\"],\n",
    "        filters=[pc.field(\"energy\") > -1.0],\n",
    "        load_format=\"table\",\n",
    "    )\n",
    "\n",
    "    df = table.to_pandas()  # Converts the table to a pandas dataframe\n",
    "    print(df.head())\n",
    "    print(df.shape)\n",
    "    print(\"Done with task: read_filtered_energy_above_minus_one\")\n",
    "    print(\"-\" * 200)\n",
    "    return task_name\n",
    "\n",
    "\n",
    "start_time = time.time()\n",
    "task_name = read_filtered_energy_above_minus_one(db)\n",
    "read_filtered_energy_above_minus_one_time = time.time() - start_time\n",
    "\n",
    "task_benchmark_dict[\"task_names\"].append(task_name)\n",
    "task_benchmark_dict[\"task_times\"].append(read_filtered_energy_above_minus_one_time)\n",
    "\n",
    "print(\n",
    "    f\"Time to read from parquetdb: {read_filtered_energy_above_minus_one_time:.2f} seconds\"\n",
    ")\n",
    "print(f\"Time to read from json: {total_time_to_read_from_json:.2f} seconds\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Reading records filtered by spg 204\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting task: read_filtered_spg_204\n",
      "      id  data.spg\n",
      "0  10113       204\n",
      "1  10125       204\n",
      "2  10126       204\n",
      "3  10133       204\n",
      "4  10140       204\n",
      "(7240, 2)\n",
      "Done with task: read_filtered_spg_204\n",
      "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n",
      "Time to read from parquetdb: 0.05 seconds\n",
      "Time to read from json: 0.00 seconds\n"
     ]
    }
   ],
   "source": [
    "def read_filtered_spg_204(db):\n",
    "    task_name = \"read_filtered_spg_204_table\"\n",
    "\n",
    "    print(\"Starting task: read_filtered_spg_204\")\n",
    "    table = db.read(\n",
    "        columns=[\"id\", \"data.spg\"],\n",
    "        filters=[pc.field(\"data.spg\") == 204],\n",
    "        load_format=\"table\",\n",
    "    )\n",
    "\n",
    "    df = table.to_pandas()  # Converts the table to a pandas dataframe\n",
    "    print(df.head())\n",
    "    print(df.shape)\n",
    "\n",
    "    print(\"Done with task: read_filtered_spg_204\")\n",
    "    print(\"-\" * 200)\n",
    "    return task_name\n",
    "\n",
    "\n",
    "start_time = time.time()\n",
    "task_name = read_filtered_spg_204(db)\n",
    "read_filtered_spg_204_time = time.time() - start_time\n",
    "\n",
    "task_benchmark_dict[\"task_names\"].append(task_name)\n",
    "task_benchmark_dict[\"task_times\"].append(read_filtered_spg_204_time)\n",
    "\n",
    "print(f\"Time to read from parquetdb: {read_filtered_spg_204_time:.2f} seconds\")\n",
    "print(f\"Time to read from json: {total_time_to_read_from_json:.2f} seconds\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Reading records filtered by spg batches\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting task: read_filtered_spg_batches\n",
      "Total number of rows: 7240, Batches: 4390\n",
      "Done with task: read_filtered_spg_batches\n",
      "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n",
      "Time to read from parquetdb: 0.76 seconds\n",
      "Time to read from json: 0.00 seconds\n"
     ]
    }
   ],
   "source": [
    "def read_filtered_spg_batches(db):\n",
    "    task_name = \"read_filtered_spg_batches\"\n",
    "    print(\"Starting task: read_filtered_spg_batches\")\n",
    "    generator = db.read(\n",
    "        load_format=\"batches\",\n",
    "        batch_size=1000,\n",
    "        load_config=LoadConfig(\n",
    "            batch_readahead=10,\n",
    "            fragment_readahead=2,\n",
    "            fragment_scan_options=None,\n",
    "            use_threads=True,\n",
    "            memory_pool=None,\n",
    "        ),\n",
    "        columns=[\"id\", \"data.spg\"],\n",
    "        filters=[pc.field(\"data.spg\") == 204],\n",
    "    )\n",
    "\n",
    "    batch_count = 0\n",
    "    num_rows = 0\n",
    "    for table in generator:\n",
    "        df = table.to_pandas()\n",
    "        num_rows += table.num_rows\n",
    "        batch_count += 1\n",
    "    print(f\"Total number of rows: {num_rows}, Batches: {batch_count}\")\n",
    "    print(\"Done with task: read_filtered_spg_batches\")\n",
    "    print(\"-\" * 200)\n",
    "    return task_name\n",
    "\n",
    "\n",
    "start_time = time.time()\n",
    "task_name = read_filtered_spg_batches(db)\n",
    "read_filtered_spg_batches_time = time.time() - start_time\n",
    "\n",
    "task_benchmark_dict[\"task_names\"].append(task_name)\n",
    "task_benchmark_dict[\"task_times\"].append(read_filtered_spg_batches_time)\n",
    "\n",
    "print(f\"Time to read from parquetdb: {read_filtered_spg_batches_time:.2f} seconds\")\n",
    "print(f\"Time to read from json: {total_time_to_read_from_json:.2f} seconds\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Reading lattice matrix for space group 204\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting task: read_lattice_matrix_spg_204\n",
      "(7240, 3, 3)\n",
      "Done with task: read_lattice_matrix_spg_204\n",
      "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n",
      "Time to read from parquetdb: 0.63 seconds\n",
      "Time to read from json: 0.00 seconds\n"
     ]
    }
   ],
   "source": [
    "def read_lattice_matrix_spg_204(db):\n",
    "    task_name = \"read_lattice_matrix_spg_204\"\n",
    "\n",
    "    print(\"Starting task: read_lattice_matrix_spg_204\")\n",
    "\n",
    "    table = db.read(\n",
    "        columns=[\"structure.lattice.matrix\"], filters=[pc.field(\"data.spg\") == 204]\n",
    "    )\n",
    "    lattice = table[\"structure.lattice.matrix\"].combine_chunks().to_numpy_ndarray()\n",
    "    print(lattice.shape)\n",
    "    print(\"Done with task: read_lattice_matrix_spg_204\")\n",
    "    print(\"-\" * 200)\n",
    "    return task_name\n",
    "\n",
    "\n",
    "start_time = time.time()\n",
    "task_name = read_lattice_matrix_spg_204(db)\n",
    "read_lattice_matrix_spg_204_time = time.time() - start_time\n",
    "\n",
    "task_benchmark_dict[\"task_names\"].append(task_name)\n",
    "task_benchmark_dict[\"task_times\"].append(read_lattice_matrix_spg_204_time)\n",
    "\n",
    "print(f\"Time to read from parquetdb: {read_lattice_matrix_spg_204_time:.2f} seconds\")\n",
    "print(f\"Time to read from json: {total_time_to_read_from_json:.2f} seconds\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Reading nested column selection\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting task: read_nested_column_selection\n",
      "(4389295, 2)\n",
      "list<element: struct<abc: list<element: double>, label: string, properties: struct<charge: double, forces: list<element: double>, magmom: double>, species: list<element: struct<element: string, occu: int64>>, xyz: list<element: double>>>\n",
      "list<element: struct<abc: list<element: double>, label: string, properties: struct<charge: double, forces: list<element: double>, magmom: double>, species: list<element: struct<element: string, occu: int64>>, xyz: list<element: double>>>\n",
      "Done with task: read_nested_column_selection\n",
      "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n",
      "Time to read from parquetdb: 3.53 seconds\n",
      "Time to read from json: 0.00 seconds\n"
     ]
    }
   ],
   "source": [
    "def read_nested_column_selection(db):\n",
    "    task_name = \"read_nested_column_selection\"\n",
    "\n",
    "    print(\"Starting task: read_nested_column_selection\")\n",
    "    table = db.read(columns=[\"id\", \"structure.sites\"], load_format=\"table\")\n",
    "\n",
    "    print(table.shape)\n",
    "    print(table[\"structure.sites\"].type)\n",
    "    print(table[\"structure.sites\"].combine_chunks().type)\n",
    "    print(\"Done with task: read_nested_column_selection\")\n",
    "    print(\"-\" * 200)\n",
    "    return task_name\n",
    "\n",
    "\n",
    "start_time = time.time()\n",
    "task_name = read_nested_column_selection(db)\n",
    "read_nested_column_selection_time = time.time() - start_time\n",
    "\n",
    "task_benchmark_dict[\"task_names\"].append(task_name)\n",
    "task_benchmark_dict[\"task_times\"].append(read_nested_column_selection_time)\n",
    "\n",
    "print(f\"Time to read from parquetdb: {read_nested_column_selection_time:.2f} seconds\")\n",
    "print(f\"Time to read from json: {total_time_to_read_from_json:.2f} seconds\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Nested structure into class"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting task: read_nested_structure_into_class\n",
      "(2, 3)\n",
      "struct<band_gap_dir: double, band_gap_ind: double, decomposition: string, dos_ef: double, e_above_hull: double, e_form: double, e_phase_separation: double, elements: list<element: string>, energy_corrected: double, energy_total: double, formula: string, location: string, mat_id: string, nsites: int64, prototype_id: string, spg: int64, stress: extension<arrow.fixed_shape_tensor[value_type=double, shape=[3,3]]>, total_mag: double>\n",
      "structure type\n",
      "struct<@class: string, @module: string, charge: int64, lattice: struct<a: double, alpha: double, b: double, beta: double, c: double, gamma: double, matrix: extension<arrow.fixed_shape_tensor[value_type=double, shape=[3,3]]>, pbc: extension<arrow.fixed_shape_tensor[value_type=bool, shape=[3]]>, volume: double>, sites: list<element: struct<abc: list<element: double>, label: string, properties: struct<charge: double, forces: list<element: double>, magmom: double>, species: list<element: struct<element: string, occu: int64>>, xyz: list<element: double>>>>\n",
      "Full Formula (Ac1 Pr12 Ho7)\n",
      "Reduced Formula: AcPr12Ho7\n",
      "abc   :  10.091510  10.091510  10.091511\n",
      "angles: 109.471217 109.471222 109.471219\n",
      "pbc   :       True       True       True\n",
      "Sites (20)\n",
      "  #  SP           a         b         c    charge  forces                                     magmom\n",
      "---  ----  --------  --------  --------  --------  ---------------------------------------  --------\n",
      "  0  Ac    0         0         0            8.076  [0.0, -0.0, -0.0]                              -0\n",
      "  1  Pr    0.476206  0.707375  0.768831     8.873  [0.0022184, 0.00231648, -0.00126846]           -0\n",
      "  2  Pr    0.938545  0.707375  0.231169     8.873  [0.00045645, 0.00231648, -0.00251434]          -0\n",
      "  3  Pr    0.523794  0.292625  0.231169     8.873  [-0.0022184, -0.00231648, 0.00126846]          -0\n",
      "  4  Pr    0.061455  0.292625  0.768831     8.873  [-0.00045645, -0.00231648, 0.00251434]         -0\n",
      "  5  Pr    0.768831  0.061455  0.292625     8.873  [0.00177791, -0.00155354, -0.00251434]         -0\n",
      "  6  Pr    0.768831  0.476206  0.707375     8.873  [-0.00089694, 0.00307943, 0.00126846]          -0\n",
      "  7  Pr    0.231169  0.938545  0.707375     8.873  [-0.00177791, 0.00155354, 0.00251434]          -0\n",
      "  8  Pr    0.231169  0.523794  0.292625     8.873  [0.00089694, -0.00307943, -0.00126846]         -0\n",
      "  9  Pr    0.707375  0.768831  0.476206     8.873  [0.00223436, 0.00076295, 0.00251434]           -0\n",
      " 10  Pr    0.292625  0.231169  0.523794     8.873  [-0.00223436, -0.00076295, -0.00251434]        -0\n",
      " 11  Pr    0.707375  0.231169  0.938545     8.873  [0.00311533, -0.00076295, 0.00126846]          -0\n",
      " 12  Pr    0.292625  0.768831  0.061455     8.873  [-0.00311533, 0.00076295, -0.00126846]         -0\n",
      " 13  Ho    0.5       0.5       0            7.546  [-0.0, -0.0, -0.0]                              0\n",
      " 14  Ho    0         0.5       0.5          7.546  [0.0, -0.0, -0.0]                               0\n",
      " 15  Ho    0.5       0         0.5          7.546  [-0.0, -0.0, -0.0]                              0\n",
      " 16  Ho    0.5       0.5       0.5          8.703  [-0.0, -0.0, -0.0]                              0\n",
      " 17  Ho    0         0         0.5          8.703  [-0.0, -0.0, -0.0]                              0\n",
      " 18  Ho    0.5       0         0            8.703  [-0.0, -0.0, -0.0]                              0\n",
      " 19  Ho    0         0.5       0            8.703  [-0.0, -0.0, -0.0]                              0\n",
      "Done with task: read_nested_structure_into_class\n",
      "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n",
      "Time to read from parquetdb: 26.94 seconds\n",
      "Time to read from json: 0.00 seconds\n"
     ]
    }
   ],
   "source": [
    "def read_nested_structure_into_class(db):\n",
    "    # By default the database flattens nested structure for storage.\n",
    "    # However, we provide an option to rebuild the nested structure. This will create a new dataset in {dataset_name}_nested.\n",
    "    # After the creation of the new dataset, the query parameters are applied to the new dataset.\n",
    "    task_name = \"read_nested_structure_into_class\"\n",
    "\n",
    "    print(\"Starting task: read_nested_structure_into_class\")\n",
    "    table = db.read(\n",
    "        columns=[\n",
    "            \"id\",\n",
    "            \"structure\",\n",
    "            \"data\",\n",
    "        ],  # Instead of using the flatten syntax, we can use the nested syntax\n",
    "        ids=[0, 1000000],\n",
    "        load_format=\"table\",\n",
    "        rebuild_nested_struct=True,  # When set to True to rebuild the nested structure\n",
    "        rebuild_nested_from_scratch=False,  # When set to True, the nested structure will be rebuilt from scratch\n",
    "        normalize_config=NormalizeConfig(\n",
    "            load_format=\"batches\",\n",
    "            batch_readahead=2,\n",
    "            fragment_readahead=1,\n",
    "            batch_size=10000,\n",
    "            max_rows_per_file=5000000,\n",
    "            min_rows_per_group=200000,\n",
    "            max_rows_per_group=200000,\n",
    "        ),\n",
    "    )\n",
    "\n",
    "    print(table.shape)\n",
    "    print(table[\"data\"].type)\n",
    "\n",
    "    print(\"structure type\")\n",
    "    print(table[\"structure\"].type)\n",
    "    try:\n",
    "        from pymatgen.core.structure import Structure\n",
    "\n",
    "        structure = Structure.from_dict(\n",
    "            table[\"structure\"].combine_chunks().to_pylist()[0]\n",
    "        )\n",
    "\n",
    "        print(structure)\n",
    "    except Exception as e:\n",
    "        print(e)\n",
    "    print(\"Done with task: read_nested_structure_into_class\")\n",
    "    print(\"-\" * 200)\n",
    "    return task_name\n",
    "\n",
    "\n",
    "start_time = time.time()\n",
    "read_nested_structure_into_class(db)\n",
    "nested_structure_time = time.time() - start_time\n",
    "\n",
    "print(f\"Time to read from parquetdb: {nested_structure_time:.2f} seconds\")\n",
    "print(f\"Time to read from json: {total_time_to_read_from_json:.2f} seconds\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the previous cell it takes ~ 60 seconds to perform the operation, this is due to reconstructing the nested structure. Further queries will be faster as the nested structure is already built.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting task: read_nested_structure_into_class\n",
      "(2, 3)\n",
      "struct<band_gap_dir: double, band_gap_ind: double, decomposition: string, dos_ef: double, e_above_hull: double, e_form: double, e_phase_separation: double, elements: list<element: string>, energy_corrected: double, energy_total: double, formula: string, location: string, mat_id: string, nsites: int64, prototype_id: string, spg: int64, stress: extension<arrow.fixed_shape_tensor[value_type=double, shape=[3,3]]>, total_mag: double>\n",
      "structure type\n",
      "struct<@class: string, @module: string, charge: int64, lattice: struct<a: double, alpha: double, b: double, beta: double, c: double, gamma: double, matrix: extension<arrow.fixed_shape_tensor[value_type=double, shape=[3,3]]>, pbc: extension<arrow.fixed_shape_tensor[value_type=bool, shape=[3]]>, volume: double>, sites: list<element: struct<abc: list<element: double>, label: string, properties: struct<charge: double, forces: list<element: double>, magmom: double>, species: list<element: struct<element: string, occu: int64>>, xyz: list<element: double>>>>\n",
      "Full Formula (Ac1 Pr12 Ho7)\n",
      "Reduced Formula: AcPr12Ho7\n",
      "abc   :  10.091510  10.091510  10.091511\n",
      "angles: 109.471217 109.471222 109.471219\n",
      "pbc   :       True       True       True\n",
      "Sites (20)\n",
      "  #  SP           a         b         c    charge  forces                                     magmom\n",
      "---  ----  --------  --------  --------  --------  ---------------------------------------  --------\n",
      "  0  Ac    0         0         0            8.076  [0.0, -0.0, -0.0]                              -0\n",
      "  1  Pr    0.476206  0.707375  0.768831     8.873  [0.0022184, 0.00231648, -0.00126846]           -0\n",
      "  2  Pr    0.938545  0.707375  0.231169     8.873  [0.00045645, 0.00231648, -0.00251434]          -0\n",
      "  3  Pr    0.523794  0.292625  0.231169     8.873  [-0.0022184, -0.00231648, 0.00126846]          -0\n",
      "  4  Pr    0.061455  0.292625  0.768831     8.873  [-0.00045645, -0.00231648, 0.00251434]         -0\n",
      "  5  Pr    0.768831  0.061455  0.292625     8.873  [0.00177791, -0.00155354, -0.00251434]         -0\n",
      "  6  Pr    0.768831  0.476206  0.707375     8.873  [-0.00089694, 0.00307943, 0.00126846]          -0\n",
      "  7  Pr    0.231169  0.938545  0.707375     8.873  [-0.00177791, 0.00155354, 0.00251434]          -0\n",
      "  8  Pr    0.231169  0.523794  0.292625     8.873  [0.00089694, -0.00307943, -0.00126846]         -0\n",
      "  9  Pr    0.707375  0.768831  0.476206     8.873  [0.00223436, 0.00076295, 0.00251434]           -0\n",
      " 10  Pr    0.292625  0.231169  0.523794     8.873  [-0.00223436, -0.00076295, -0.00251434]        -0\n",
      " 11  Pr    0.707375  0.231169  0.938545     8.873  [0.00311533, -0.00076295, 0.00126846]          -0\n",
      " 12  Pr    0.292625  0.768831  0.061455     8.873  [-0.00311533, 0.00076295, -0.00126846]         -0\n",
      " 13  Ho    0.5       0.5       0            7.546  [-0.0, -0.0, -0.0]                              0\n",
      " 14  Ho    0         0.5       0.5          7.546  [0.0, -0.0, -0.0]                               0\n",
      " 15  Ho    0.5       0         0.5          7.546  [-0.0, -0.0, -0.0]                              0\n",
      " 16  Ho    0.5       0.5       0.5          8.703  [-0.0, -0.0, -0.0]                              0\n",
      " 17  Ho    0         0         0.5          8.703  [-0.0, -0.0, -0.0]                              0\n",
      " 18  Ho    0.5       0         0            8.703  [-0.0, -0.0, -0.0]                              0\n",
      " 19  Ho    0         0.5       0            8.703  [-0.0, -0.0, -0.0]                              0\n",
      "Done with task: read_nested_structure_into_class\n",
      "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n",
      "Time to read from parquetdb: 2.67 seconds\n",
      "Time to read from json: 0.00 seconds\n"
     ]
    }
   ],
   "source": [
    "start_time = time.time()\n",
    "task_name = read_nested_structure_into_class(db)\n",
    "nested_structure_time = time.time() - start_time\n",
    "\n",
    "task_benchmark_dict[\"task_names\"].append(task_name)\n",
    "task_benchmark_dict[\"task_times\"].append(nested_structure_time)\n",
    "\n",
    "print(f\"Time to read from parquetdb: {nested_structure_time:.2f} seconds\")\n",
    "print(f\"Time to read from json: {total_time_to_read_from_json:.2f} seconds\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Plotting times"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from parquetdb.utils import matplotlib_utils\n",
    "from matplotlib import rcParams\n",
    "from mpl_toolkits.axes_grid1.inset_locator import inset_axes\n",
    "\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "tags": [
     "nbsphinx-thumbnail"
    ]
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\lllang\\AppData\\Local\\Temp\\ipykernel_67684\\1793184629.py:57: UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect.\n",
      "  plt.tight_layout()\n"
     ]
    },
    {
     "data": {
      "image/png": "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GCDOnDmjdbnc5/revXuif//+wsHBQRgYGIhy5cqJoUOHiocPH2pd/u7du2LixImidu3awtzcXBgYGAgHBwfh6ekpIiMj1bad3weJgwcPCj8/P1GyZElhYmIiqlatKqZNmyaeP3+e541mXFycaNSokTA3N5ce9HKf87yulfT0dBETEyNq1qwpTExMhJGRkXB3dxfjxo3T+JksbOJg27ZtYsCAAaJWrVrC1tZWOma+vr5i+fLl4sWLF3keG02OHz8uOnbsKOzs7ISenp6wsbERrVu3Frt379ZY/m0lDoQQYsmSJcLDw0MYGRkJS0tL4e/vL/bv35/n9+qZM2dEYGCgKFOmjDAyMhIVK1YUo0ePFo8fP84z1oMHDwp/f39hbW0tPQDkjvnJkydi3LhxwtXVVRgZGYlSpUqJdu3aiT///FNjPC9fvhQ//PCD6NKli3BzcxOWlpbC2NhYyOVy0aFDB7F3716t+13Q7/Xs7GwRExMjqlSpIj0AFfSh6+rVq9Jy06ZNU5uvTGjIZDLx33//aVxHXp+n1x3fDyVxIIQQz58/F3PmzBFeXl7C2tpa6OrqCgsLC9GgQQPx9ddfi4yMjELF8yEmDoTIudbnz58vGjRoIH13y+VyMWTIEPHvv/9qjLm4EgdCFO4eVQghFi9eLMV95MgRtfnKhJK7u7vG5VetWiV69eolqlatKkqUKCEMDQ2Fk5OTaNmypYiLi9OYkM+LTIj3pFtfIiIiogJYtmwZevXqhZ49e77zzt2IiIg+JezjgIiIiIiIiIi0YuKAiIiIiIiIiLRi4oCIiIiIiIiItGIfB0RERERERESkFWscEBEREREREZFWTBwQERERERERkVZ6xR0AEdHHRqFQ4Pbt2zA3N4dMJivucIiIiIjoLRBC4MmTJ7C3t4eOzsf9Tp6JAyKiInb79m2UK1euuMMgIiIionfg1q1bcHBwKO4w3iomDoiIipi5uTmAnB8RCwuLYo6GiIiIiN6Gx48fo1y5ctK938eMiQMioiKmbJ5gYWHBxAERERHRR+5TaJr6cTfEICIiIiIiIqI3wsQBEREREREREWnFxAERERERERERacXEARERERERERFpxcQBEREREREREWnFxAERERERERERacXEARERERERERFpxcQBEREREREREWnFxAERERERERERacXEARERERERERFpxcQBEREREREREWnFxAERERERERERacXEARERERERERFpxcQBEREREREREWnFxAERERERERERacXEARERERERERFpxcQBEREREREREWnFxAERERERERERacXEARERERERERFpxcQBEREREREREWmlV9wBEBF9rDZdT4KJuXlxh0FERMWoY3mX4g6BiOiNscYBEREREREREWnFxAERERERERERacXEARERERERERFpxcQBEREREREREWnFxAERERERERERacXEARERERERERFpxcQBEREREREREWnFxAERERERERERacXEARERERERERFpxcQBEREREREREWnFxAERERERERERacXEARERERERERFpxcTBOxQWFgZnZ+fiDqNYRUVFQSaTFXcYn7SP4TpctmwZZDIZkpKSijsUIiIiIqKP3nubOPjrr7/QokULWFhYwNzcHAEBATh9+nRxh/VJuH37NqKioj6o4z1//nwsW7bsk4/hbdu+fTuioqKKOwwiIiIiInqH3svEwcmTJ+Hl5YVr164hMjISkyZNQmJiInx8fHDp0qXiDu+jd/v2bURHRzNx8AHGkB+LFi0q9Odo+/btiI6OLuKIiIiIiIjofaZX3AFoMnHiRBgbG+PYsWOwsbEBAHTv3h2VKlXCuHHjsHHjxiLZTnp6OkxNTYtkXfTh+JDOuxACz549g7GxcZGtU19fv8jWRUREREREH7/3ssbBoUOH4O/vLyUNAKBMmTLw8fHBtm3b8PTp0wKvU9m2/vz58+jatSusra3h5eUlzV+1ahU8PDxgbGyMEiVKICQkBLdu3VKLq1OnTnB0dIShoSHKlSuHL774ApmZmWrb27RpE6pWrQojIyNUrVoVcXFxBY4ZAHx9fVG1alWcP38eTZo0gYmJCcqWLYuZM2eqlX3+/DkiIyNRoUIFKb7Ro0fj+fPnKuXi4+Ph5eUFKysrmJmZwdXVFePGjQMAHDhwAHXr1gUA9OrVCzKZDDKZTOVN+okTJ9CiRQtYWlrCxMQEPj4+OHLkiFo8hw8fRt26dWFkZAS5XI6FCxcW6hj8999/6NWrFxwcHGBoaIgyZcrgs88+k9q3Ozs749y5c0hISJDi9fX1BfC/tvAJCQkYOHAgSpUqBQcHBwDa2/pr64dh1apVqFevHkxMTGBtbY3GjRtj9+7dr41B2/o0tdN3dnZGmzZtsGvXLtSp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RB8ado5IRFTE2DkiERHRp42dI34a2DkiERERERERERGYOCAiIiIiIiKiPDBxQERERERERERaMXFARERERERERFoxcUBEREREREREWjFxQERERERERERaMXFARERERERERFrpFXcAREQfqzJdP/4xfYmIiIjo48caB0RERERERESkFRMHRERERERERKQVEwdEREREREREpBUTB0RERERERESkFRMHRERERERERKQVEwdEREREREREpBUTB0RERERERESkFRMHRERERERERKQVEwdEREREREREpJVecQdARPSxsly7BDA2Lu4wPnqie//iDoGIiIjoo8YaB0RERERERESkFRMHRERERERERKQVEwdEREREREREpBUTB0RERERERESkFRMHRERERERERKQVEwdEREREREREpBUTB0RERERERESkFRMHRERERERERKQVEwdEREREREREpBUTB0RERERERESkFRMHRERERERERKQVEwdEREREREREpBUTB0RERERERESkFRMHhLCwMDg7O7/1Zd6Es7MzwsLC3tn2PjS+vr7w9fUt7jCIiIiIiOgjxMRBAYSFhUEmk2n9l5ycXNwhfhCmT5+OTZs2qU0/evQooqKikJqa+s5jel/cvn0bUVFROH36dHGH8l5TKBRYtmwZAgMDUa5cOZiamqJq1aqYOnUqnj17pnGZxYsXw93dHUZGRqhYsSLmzp372u00a9YMMpkMgwcPLupdICIiIiL6YOgVdwAfkv79+8Pf319lmhAC4eHhcHZ2RtmyZYspsg/L9OnT0bFjR7Rr105l+tGjRxEdHY2wsDBYWVmpzLt06RJ0dD7+PNft27cRHR0NZ2dn1KxZM9/L7d69++0F9R7KyMhAr1690KBBA4SHh6NUqVI4duwYIiMjsXfvXuzbtw8ymUwqv3DhQoSHh6NDhw748ssvcejQIQwdOhQZGRkYM2aMxm38+uuvOHbs2LvaJSIiIiKi9xYTBwXQsGFDNGzYUGXa4cOHkZGRgW7duhXZdtLT02Fqalpk6/sYGBoaFncI76WMjAyYmJjAwMCguEN5pwwMDHDkyBF4enpK0z7//HM4OztLyQNlki8zMxPjx49H69atsWHDBqmsQqHAlClT0K9fP1hbW6us/9mzZxgxYgTGjBmDSZMmvbsdIyIiIiJ6D338r3DfsjVr1kAmk6Fr166F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REQEJg6IiIiIiIiIKA9MHBARERERERGRVkwcEBEREREREZFWTBwQERERERERkVZMHBARERERERGRVkwcEBEREREREZFWesUdABHRxyqtc++PfkxfIiIiIvr4scYBEREREREREWnFxAERERERERERacXEARERERERERFpxcQBEREREREREWnFxAERERERERERacXEARERERERERFpxcQBEREREREREWnFxAERERERERERacXEARERERERERFppVfcARARfazu1LDFUx1ZcYdBBWB/9Vlxh0BERJ84X19fAMCBAweKNQ6i3FjjgIiIiIiI3gvLli2DTCbDn3/+WdyhAAAOHz6Mli1bomzZsjAyMoKjoyPatm2LNWvWFHdoRO8UEwdERERERESvWL9+PRo3boy7d+9i2LBhmDt3Lrp3745Hjx5h0aJFxR0e0TvFpgpERERERESviIqKQuXKlXH8+HEYGBiozLt3714xRUVUPFjjgIiIiIiIPiinTp1Cy5YtYWFhATMzM/j5+eH48eNq5c6cOQMfHx8YGxvDwcEBU6dOxdKlSyGTyZCUlJTnNq5evYq6deuqJQ0AoFSpUip/KxQKzJkzB9WqVYORkRFsbW3RokULlSYXS5cuRdOmTVGqVCkYGhqicuXKWLBgQb729/nz54iMjESFChVgaGiIcuXKYfTo0Xj+/Hm+lid6U6xxQEREREREH4xz587B29sbFhYWGD16NPT19bFw4UL4+voiISEB9evXBwAkJyejSZMmkMlkiIiIgKmpKX766ScYGhrmaztOTk7Yu3cv/v33Xzg4OORZtk+fPli2bBlatmyJvn37IisrC4cOHcLx48dRp04dAMCCBQtQpUoVBAYGQk9PD1u3bsXAgQOhUCgwaNAgretWKBQIDAzE4cOH0a9fP7i7u+Ps2bOIjY3F5cuXsWnTpvwdOKI3wMQBERERERF9MCZMmICXL1/i8OHDKF++PAAgNDQUrq6uGD16NBISEgAAM2bMwKNHj3Dy5EnUrFkTANCrVy9UrFgxX9sZM2YM+vTpA7lcjkaNGsHLywsBAQHw9PSEjs7/Km7v378fy5Ytw9ChQzFnzhxp+ogRIyCEkP5OSEiAsbGx9PfgwYPRokULzJo1K8/EwZo1a7Bnzx4kJCTAy8tLml61alWEh4fj6NGj8PT0zNc+ERUWmyoQEREREdEH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5jU8jRk6dChat26dbZ2iPDKEiIioNDl58iSWLVuGS5cu4cWLF9i3bx969uypUGflypVYtmwZXr58iXr16iE4OBhNmzbVTsDFTH779/nz52LSAAAqVaqEZ8+eFeYpUAnGxAGVSC4uLnBxcdF2GFpnbm4Od3d3bYehkpOTE5ycnLQdBhEREeVCYmIi6tWrh+HDh6N3795K23fs2IGpU6di9erVaNasGZYvXw5PT0/cvXsXVlZWAID69esjPT1dad/Dhw8rraRV2miif4kKChMHRERERESUo86dO6Nz584qt//4448YOXKkuPz06tWr8ddff2H9+vWYPXs2gI+rRFHW8tu/tra2CiMMnj17xtEepDFcVYGIiIiIiPIlNTUVly5dUhjpqKOjA3d3d5w7d06LkZUMuenfpk2b4r///sOzZ8+QkJCAgwcPwtPTU1shUwnDEQdERERERJQvb968QUZGBipWrKhQXrFiRdy5cyfX7bi7u+PatWtITExE5cqVsWvXLrRo0ULT4RY7uelfPT09/PDDD2jfvj3kcjlmzpzJFRVIY5g4ICIiIiKiIuHIkSPaDqFY6969O7p3767tMKgE4qsKRERERESULxUqVICuri5evXqlUP7q1SuukKQB7F/SNiYOiIiIiIgoX/T19dGoUSMcPXpULJPL5Th69ChfNdAA9i9pG19VICIiIiKiHCUkJOD+/fvi96ioKFy9ehUWFhawt7fH1KlT4ePjg8aNG6Np06ZYvnw5EhMTxVUAKHvsXyrKJIIgCNoOgoioJImPj4dUKoVMJoOZmZm2wyEiItKIiIgItG/fXqncx8cHoaGhAIAVK1Zg2bJlePnyJerXr49ffvkFzZo1K+RIiyf2b/FTmv7Nx8QBEZGGlaa/RIiIiIhKq9L0bz7OcUBEREREREREKjFxQEREREREREQqMXFARERERERERCoxcUBEREREREREKjFxQEREREREREQqMXFARERERERERCoxcUBEREREREREKjFxQEREREREREQq6Wk7ACKikkq6Yz1gZKTtMIiIiIhKPGHwaG2HUKJxxAERERERERERqcTEARERERERERGpxMQBEREREREREanExAERERERERERqcTEARERERERERGpxMQBEREREREREanExAERERERERERqcTEARERERERERGpxMQBEREREREREanExAER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qlWr0KRJEwwePFhl+1KpFP369UNwcDAkEgmcnZ3x559/5noOBiIiIiIiyj8mDkjjvv/+e4Wh5Hv37sXevXsBAIMHDxYTB5owcOBA2NraYvHixVi2bBlSUlJQqVIluLm5YdiwYWK9bdu2YcKECVi5ciUEQYCHhwcOHjwIW1tbhfbq1q2LsLAwTJ06Ff7+/qhcuTICAwPx4sWLPCUO7OzsMGDAABw9ehSbN2+Gnp4eatasiZ07d6JPnz4aOffx48dDEAT88MMPmD59OurVq4cDBw5g4sSJMDQ0zHZfFxcX/PvvvwgMDERoaCjevn0LKysrNGjQQOF1jtz47rvv4OjoiODgYHz77bcoW7Ys6tatiyFDhoh15s2bB0tLS6xYsQJTpkyBhYUFRo0ahUWLFqFMmTLZth8cHIy0tDSsXr0aBgYG8PLywrJly1C7du08xUlEREREROqRCJqYbY2IigS5XA5LS0v07t0bv/76q7bDKbXi4+MhlUpxx0Efpjr/N/rD9kFyNnsRERERUXGS+W8+mUwGMzMzbYdToDjHAVExlZycrDRvw6ZNm/Du3Tu0a9dOO0EREREREVGJw1cViPJIJpMhKSkp2zpZLQ+paefPn8eUKVPQr18/lC9fHpcvX8a6detQu3Zt9OvXL9/tv3z5MtvtRkZGGn3thIiIiIiIiiYmDojyaNKkSdi4cWO2dQrjDSAHBwfY2dnhl19+wbt372BhYYGhQ4di8eLF0NfXz3f7NjY22W738fFBaGhovo9DRERERERFG+c4IMqjW7duiStGqOLu7l5I0RScI0eOZLvd1tYWLi4uhRRN8cI5DoiIiIhKvtI0xwETB0REGsbEAREREVHJV5oSB5wckYiIiIiIiIhUYuKAiIiIiIiIiFRi4oCIiIiIiIiIVGLigIiIiIiIiIhUYuKAiIiIiIiIiFRi4oCIiIiIiIiIVGLigIiIiIiIiIhU0tN2AEREJZXNtZgSv6YvEREREZV8HHFARERERERERCoxcUBEREREREREKjFxQEREREREREQqMXFARERERERERCoxcUBEREREREREKjFxQEREREREREQqMXFARERERERERCoxcUBEREREREREKjFxQEREREREREQqMXFARERERERERCoxcUBEREREREREKjFxQEREREREREQqMXFARERERERERCoxcUBERERERERE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",
      "text/plain": [
       "<Figure size 1000x600 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "xlabel_size = 16\n",
    "ylabel_size = 16\n",
    "title_size = 16\n",
    "xtick_size = 14\n",
    "ytick_size = 12\n",
    "\n",
    "inset_xtick_size = 10\n",
    "inset_ytick_size = 10\n",
    "inset_title_size = 12\n",
    "\n",
    "labels = task_benchmark_dict[\"task_names\"]\n",
    "times = task_benchmark_dict[\"task_times\"]\n",
    "# Create the main plot with numbered x labels and an inset showing the same data on a log scale\n",
    "fig, ax = plt.subplots(figsize=(10, 6))\n",
    "\n",
    "# Number the labels\n",
    "numbered_labels = [f\"{i+1}. {label}\" for i, label in enumerate(labels)]\n",
    "\n",
    "# matplotlib_utils.set_palette('Cavalcanti1')\n",
    "matplotlib_utils.set_palette(\"Darjeeling1_alt\")\n",
    "# matplotlib_utils.set_palette('Zissou1')\n",
    "# matplotlib_utils.set_palette('AsteroidCity1')\n",
    "# matplotlib_utils.set_palette('BottleRocket2')\n",
    "colors = rcParams[\"axes.prop_cycle\"].by_key()[\"color\"]\n",
    "# Main horizontal bar plotcolors[:len(times)]\n",
    "# ax.barh(numbered_labels, times, color=\"#59b9de\")\n",
    "ax.barh(numbered_labels, times, color=colors[: len(times)])\n",
    "ax.set_xlabel(\"Total Time (seconds)\", fontsize=xlabel_size)\n",
    "ax.set_ylabel(\"Operations\", fontsize=ylabel_size)\n",
    "\n",
    "ax.tick_params(axis=\"x\", labelsize=xtick_size)\n",
    "ax.tick_params(axis=\"y\", labelsize=ytick_size)\n",
    "ax.set_title(\n",
    "    \"Total Time for Various Operations on dataset with 4.8 million rows\",\n",
    "    fontsize=title_size,\n",
    ")\n",
    "\n",
    "# Inset plot with log scale and just the numbers\n",
    "# ax_inset = inset_axes(ax, width=\"40%\", height=\"30%\", loc=\"center right\")\n",
    "\n",
    "ax_inset = inset_axes(\n",
    "    ax,\n",
    "    width=\"30%\",\n",
    "    height=\"30%\",\n",
    "    loc=\"center right\",\n",
    "    bbox_to_anchor=(-0.05, -0.05, 1, 1),\n",
    "    bbox_transform=ax.transAxes,\n",
    ")\n",
    "ax_inset.barh(range(1, len(labels) + 1), times, color=\"#e52207\")\n",
    "ax_inset.barh(range(1, len(labels) + 1), times, color=colors[: len(times)])\n",
    "ax_inset.set_xscale(\"log\")\n",
    "ax_inset.set_yticks(range(1, len(labels) + 1))  # Show just the numbers\n",
    "ax_inset.set_yticklabels(range(1, len(labels) + 1), fontsize=inset_ytick_size)\n",
    "ax_inset.set_title(\"Log Scale\", fontsize=inset_title_size)\n",
    "\n",
    "# Adjust layout and show the plot\n",
    "plt.tight_layout()\n",
    "\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "parquetdb_dev",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.20"
  },
  "nbsphinx": {
   "execute": "never"
  },
  "nbsphinx-thumbnail": {
   "tooltip": "In this example, we store the 3D Alexandria dataset in ParquetDB and record the performance various operations on it."
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
